import kotlin.math.sqrt
import kotlin.system.getTimeNanos

fun main(args: Array<String>) {
    val n = if (args.isNotEmpty()) args[0].toInt() else 1000
    // 严格按照24次迭代，每次输出"初始能量→最终能量→时间"三组数据
    repeat(24) {
        // 每次迭代重新初始化系统，确保独立计算
        val bodies = NBodySystem2()

        // 记录开始时间
        val startTime = getTimeNanos()

        // 计算初始能量
        val initialEnergy = bodies.energy()

        // 执行N次迭代
        repeat(n) {
            bodies.advance(0.01)
        }

        // 计算最终能量
        val finalEnergy = bodies.energy()

        // 计算耗时
        val duration = (getTimeNanos() - startTime) / 1.0e9

        // 按顺序输出：初始能量 → 最终能量 → 时间（每组占一行）
        println(formatEnergy(initialEnergy))
        println(formatEnergy(finalEnergy))
        println(formatTime(duration))
    }
}

// 修复能量值格式化（确保负数正确显示，保留9位小数）
private fun formatEnergy(value: Double): String {
    // 处理符号
    val sign = if (value < 0) "-" else ""
    val absValue = kotlin.math.abs(value)

    // 分离整数和小数部分
    val integerPart = absValue.toInt()
    val fractionalPart = (absValue - integerPart) * 1000000000.0 + 0.5 // 四舍五入

    // 小数部分补零至9位
    val fracStr = fractionalPart.toLong()
        .toString()
        .padStart(9, '0') // 不足9位补零
        .take(9) // 超过9位截取

    return "$sign$integerPart.$fracStr"
}

// 时间格式化（保留3位小数）
private fun formatTime(value: Double): String {
    val integerPart = value.toInt()
    val fractionalPart = (value - integerPart) * 1000.0 + 0.5 // 四舍五入
    val fracStr = fractionalPart.toInt()
        .toString()
        .padStart(3, '0')
        .take(3)
    return "$integerPart.$fracStr"
}

class NBodySystem2 {
    private val bodies = arrayOf(
        Body3.sun(),
        Body3.jupiter(),
        Body3.saturn(),
        Body3.uranus(),
        Body3.neptune()
    )

    init {
        // 计算初始动量并抵消太阳动量
        var px = 0.0
        var py = 0.0
        var pz = 0.0
        bodies.forEach {
            px += it.vx * it.mass
            py += it.vy * it.mass
            pz += it.vz * it.mass
        }
        bodies[0].offsetMomentum(px, py, pz)
    }

    fun advance(dt: Double) {
        // 计算星体间的相互作用
        for (i in bodies.indices) {
            for (j in i + 1 until bodies.size) {
                val dx = bodies[i].x - bodies[j].x
                val dy = bodies[i].y - bodies[j].y
                val dz = bodies[i].z - bodies[j].z

                val distance = sqrt(dx * dx + dy * dy + dz * dz)
                val mag = dt / (distance * distance * distance)

                // 更新速度
                bodies[i].vx -= dx * bodies[j].mass * mag
                bodies[i].vy -= dy * bodies[j].mass * mag
                bodies[i].vz -= dz * bodies[j].mass * mag

                bodies[j].vx += dx * bodies[i].mass * mag
                bodies[j].vy += dy * bodies[i].mass * mag
                bodies[j].vz += dz * bodies[i].mass * mag
            }
        }

        // 更新位置
        bodies.forEach {
            it.x += dt * it.vx
            it.y += dt * it.vy
            it.z += dt * it.vz
        }
    }

    fun energy(): Double {
        var energy = 0.0

        // 动能
        bodies.forEach {
            energy += 0.5 * it.mass * (it.vx * it.vx + it.vy * it.vy + it.vz * it.vz)
        }

        // 势能
        for (i in bodies.indices) {
            for (j in i + 1 until bodies.size) {
                val dx = bodies[i].x - bodies[j].x
                val dy = bodies[i].y - bodies[j].y
                val dz = bodies[i].z - bodies[j].z
                val distance = sqrt(dx * dx + dy * dy + dz * dz)
                energy -= (bodies[i].mass * bodies[j].mass) / distance
            }
        }

        return energy
    }
}

class Body3 {
    var x = 0.0
    var y = 0.0
    var z = 0.0
    var vx = 0.0
    var vy = 0.0
    var vz = 0.0
    var mass = 0.0

    companion object {
        const val PI = 3.141592653589793
        val SOLAR_MASS = 4 * PI * PI // 太阳质量
        const val DAYS_PER_YEAR = 365.24 // 每年天数

        // 木星参数
        fun jupiter() = Body3().apply {
            x = 4.84143144246472090e+00
            y = -1.16032004402742839e+00
            z = -1.03622044471123109e-01
            vx = 1.66007664274403694e-03 * DAYS_PER_YEAR
            vy = 7.69901118419740425e-03 * DAYS_PER_YEAR
            vz = -6.90460016972063023e-05 * DAYS_PER_YEAR
            mass = 9.54791938424326609e-04 * SOLAR_MASS
        }

        // 土星参数
        fun saturn() = Body3().apply {
            x = 8.34336671824457987e+00
            y = 4.12479856412430479e+00
            z = -4.03523417114321381e-01
            vx = -2.76742510726862411e-03 * DAYS_PER_YEAR
            vy = 4.99852801234917238e-03 * DAYS_PER_YEAR
            vz = 2.30417297573763929e-05 * DAYS_PER_YEAR
            mass = 2.85885980666130812e-04 * SOLAR_MASS
        }

        // 天王星参数
        fun uranus() = Body3().apply {
            x = 1.28943695621391310e+01
            y = -1.51111514016986312e+01
            z = -2.23307578892655734e-01
            vx = 2.96460137564761618e-03 * DAYS_PER_YEAR
            vy = 2.37847173959480950e-03 * DAYS_PER_YEAR
            vz = -2.96589568540237556e-05 * DAYS_PER_YEAR
            mass = 4.36624404335156298e-05 * SOLAR_MASS
        }

        // 海王星参数
        fun neptune() = Body3().apply {
            x = 1.53796971148509165e+01
            y = -2.59193146099879641e+01
            z = 1.79258772950371181e-01
            vx = 2.68067772490389322e-03 * DAYS_PER_YEAR
            vy = 1.62824170038242295e-03 * DAYS_PER_YEAR
            vz = -9.51592254519715870e-05 * DAYS_PER_YEAR
            mass = 5.15138902046611451e-05 * SOLAR_MASS
        }

        // 太阳参数
        fun sun() = Body3().apply {
            mass = SOLAR_MASS
        }
    }

    // 抵消动量
    fun offsetMomentum(px: Double, py: Double, pz: Double): Body3 {
        vx = -px / SOLAR_MASS
        vy = -py / SOLAR_MASS
        vz = -pz / SOLAR_MASS
        return this
    }
}